package viz_main;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

public class Node {
    private String data; // the name of this node (eg: Georgia St.)
    private int[] indexList; // the list of indexes that have this data. (eg: index 5, 6, 7 all have Georgia St.)
    private String axisName; // the name of the axis that this node belongs to (eg: Streets)
    private int count; // the number of unique categories this node has (can also be derived from children.getSize())
    private Node parent; // link back up to the previous level of the tree.
    private ArrayList<Node> children;
    private HashMap<String, int[]> categoryCountMap;
    
    public Node(){
    	data = "";
    	categoryCountMap = new HashMap<String, int[]>();
    }
    
    public Node(String d, int n){
    	data = d;
    	count = n;
    	parent = null;
    	children = new ArrayList<Node>();
    	categoryCountMap = new HashMap<String, int[]>();
    }
    
    public Node(String dataName, int[] indexes, String axisKey, Node parentNode) {
    	data = dataName;
    	indexList = indexes;
    	axisName = axisKey;
    	count = indexes.length; // derive count based on length of array
    	parent = parentNode;
    	// initialize array for children:
    	children = new ArrayList<Node>();
    	categoryCountMap = new HashMap<String, int[]>();
    }
    
    public void addChild(String d, int n){
    	Node c = new Node(d, n);
    	this.children.add(c);
    }
    
    public void addChild(Node tmpNode)
    {
    	this.children.add(tmpNode);
    }

    public void printNode(Node n, String indent){
    	/*if(n.children.size() > 0){
    		for (int i = 0; i < n.children.size();i++){
    			printNode(n.children.get(i));
    		}
    	}*/
    	//else{
    	System.out.println(indent + n.data + " : " + n.count);
    	//}
    }
    
    public String getName(){
    	return data;
    }

    public Node getNode(int i){
    	return this.children.get(i);
    }

    public Node getNode(String s){
    	for (int i = 0; i < this.children.size(); i++){
    		if (this.children.get(i).data.equals(s)){
    			return this.children.get(i);
    		}
    	}
    	return null;
    }
    
    public int getChildrenLength(){
    	return this.children.size();
    }
    
    public ArrayList<Node> getChildren()
    {
    	return this.children;
    }
    
    public int getCount(){
    	return this.count;
    }
    
    public int[] getIndexList(){
    	return indexList;
    }
    
    public int getTotal(){
    	int total = 0;
    	for (int i = 0; i < this.getChildrenLength();i++){
    		total += this.getNode(i).getCount();
    	}
    	return total;
    }
    
    public Node getParent(){
    	return parent;
    }
    
    // checks the categoryCountMap for any record of the given category.
    // it will return the record if it exists or null if not found.
    public int[] getRecordOf(String category){
    	return categoryCountMap.get(category);
    }
    
    // this node looks in all its indexes and checks with the attributeAxis whether 
    // any of the associated values match the given attributeName
    public void createNewRecordOf(ScatterPlotCAxis attributeAxis, String attributeName){
    	for(int e = 0; e < indexList.length; e++)
    	{
    		categoryCountMap.put(attributeName, new int[]{}); // start off a new array for this new category
    		// if they equal eachother...
    		// then this is an attribute that belongs in our collection
    		if(attributeAxis.getElementAsString(indexList[e]).equals(attributeName))
    		{
    			Object countainsIndexes = categoryCountMap.get(attributeName);
    		    // append the new element to the end of the array:
    		    int[] tmpCount = (int[])countainsIndexes;
    		    countainsIndexes = new int[tmpCount.length+1];
    		    for(int i = 0; i < tmpCount.length; i++){
    		    	((int[])(countainsIndexes))[i] = tmpCount[i];
    		    }
    		    ((int[])(countainsIndexes))[tmpCount.length] = indexList[e]; // do the actual append
    		    categoryCountMap.put(attributeName, (int[])countainsIndexes); // add the array back into the hashmap. (might not be necessary)
    		}
    	}
    }
    
    // this recursive total takes a starting count value that it passes down and passes back up.
    public int getRecursiveTotal(int curTotal){
    	for(int i = 0; i < this.children.size(); i++){
    		if(children.get(i).getChildren().size() > 0)
    		{
    			curTotal = children.get(i).getRecursiveTotal(curTotal);
    		}
    		else {
    			curTotal ++;
    		}
    	}
    	return curTotal;
    }

    public void printTree(String indent){
    	System.out.println(indent + this.data);
    	for(int i = 0; i < this.children.size();i++){
    		if(children.get(i).getChildren().size() > 0)
    		{
    			children.get(i).printTree(indent + "  ");
    		}
    		else {
    			printNode(getNode(i), indent + "  ");
    		}
    	}
    }

}
